#include "GlobalHead.h"
#include "Command.h"
#include "Gui_Application.h"
#include "MainWindow.h"
#include "Action.h"
#include "BitmapFactory.h"
#include "FileDialog.h"
#include "Gui_Document.h"
#include "App/Document.h"
#include "Selection.h"
#include "DocumentObjectGroup.h"
#include "DWGImport/DWGImporter.h"
#include "TopoImport/TopoImporter.h"

#include <QFileDialog>

using namespace Gui;
DEF_STD_CMD(StdCmdOpen);
StdCmdOpen::StdCmdOpen()
:Command("Std_Open")
{
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("&Open...");
	sToolTipText  = QT_TR_NOOP("Open a document or import files");
	sWhatsThis    = "Std_Open";
	sStatusTip    = QT_TR_NOOP("Open a document or import files");
	sPixmap       = "document-open";
	sAccel        = keySequenceToAccel(QKeySequence::Open);
}

void StdCmdOpen::activated(int iMsg)
{

 	QString formatList;
 	const char* supported = QT_TR_NOOP("Supported formats");
 	const char* allFiles = QT_TR_NOOP("All files (*.*)");
 	formatList = QObject::tr(supported);
 	formatList += QLatin1String(" (");
 
 	std::vector<std::string> filetypes = GetApp_Application().getImportTypes();
 	std::vector<std::string>::iterator it;
 	// Make sure FCStd is the very first fileformat
 	it = std::find(filetypes.begin(), filetypes.end(), "cmo");
 	if (it != filetypes.end()) {
 		filetypes.erase(it);
 		filetypes.insert(filetypes.begin(), "cmo");
 	}
 	for (it=filetypes.begin();it != filetypes.end();++it) {
 		formatList += QLatin1String(" *.");
 		formatList += QLatin1String(it->c_str());
 	}
 
 	formatList += QLatin1String(");;");
 
 	std::map<std::string, std::string> FilterList = GetApp_Application().getImportFilters();
 	std::map<std::string, std::string>::iterator jt;
 	// Make sure the format name for FCStd is the very first in the list
 	for (jt=FilterList.begin();jt != FilterList.end();++jt) {
 		if (jt->first.find("*.cmo") != std::string::npos) {
 			formatList += QLatin1String(jt->first.c_str());
 			formatList += QLatin1String(";;");
 			FilterList.erase(jt);
 			break;
 		}
 	}
 	for (jt=FilterList.begin();jt != FilterList.end();++jt) {
 		formatList += QLatin1String(jt->first.c_str());
 		formatList += QLatin1String(";;");
 	}
 	formatList += QObject::tr(allFiles);
 
 	QString selectedFilter;
 	QStringList fileList = FileDialog::getOpenFileNames(getMainWindow(),
 		QObject::tr("Open document"), QString(), formatList, &selectedFilter);
 	// load the files with the associated modules
 	SelectModule::Dict dict = SelectModule::importHandler(fileList, selectedFilter);
 	for (SelectModule::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
 		getGuiApplication()->open(it.key().toUtf8(), it.value().toAscii());
 	}
}

DEF_STD_CMD_A(StdCmdDWGImport)

StdCmdDWGImport::StdCmdDWGImport()
:Command("Std_DWGImport")
{
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("&Import DWG File");
	sToolTipText  = QT_TR_NOOP("Import a DWG in the active document");
	sWhatsThis    = "Std_DWGImport";
	sStatusTip    = QT_TR_NOOP("Import a DWG in the active document");
}

void StdCmdDWGImport::activated(int iMsg)
{
	QString filename = QFileDialog::getOpenFileName(getMainWindow(),
			QObject::tr("Import DWG Files"),QString(),QString::fromLocal8Bit("DWG Files (*.dwg);;DWF Files(*.dwf)"));
	if(filename != NULL){
		DWGImporter::Instance()->showDialog(filename.toStdString());
	//	DWGImporter::Instance()->doImport(filename.toStdString());
	}
}

bool StdCmdDWGImport::isActive()
{
	return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
DEF_STD_CMD_A(StdCmdTopoImport)

StdCmdTopoImport::StdCmdTopoImport()
:Command("Std_TopoImport")
{
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("&Import Topography File");
	sToolTipText  = QT_TR_NOOP("Import a Topography file in the active document");
	sWhatsThis    = "Std_DWGImport";
	sStatusTip    = QT_TR_NOOP("Import a Topography file in the active document");
}

void StdCmdTopoImport::activated(int iMsg)
{
	TopoImporter::Instance()->showDialog();
}

bool StdCmdTopoImport::isActive()
{
	return true;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

DEF_STD_CMD_A(StdCmdImport)

StdCmdImport::StdCmdImport()
:Command("Std_Import")
{
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("&Import...");
	sToolTipText  = QT_TR_NOOP("Import a file in the active document");
	sWhatsThis    = "Std_Import";
	sStatusTip    = QT_TR_NOOP("Import a file in the active document");
	//sPixmap       = "Open";
    sAccel        = "Ctrl+I";
}

void StdCmdImport::activated(int iMsg)
{
	QString formatList;
	const char* supported = QT_TR_NOOP("Supported formats");
	const char* allFiles = QT_TR_NOOP("All files (*.*)");
	formatList = QObject::tr(supported);
	formatList += QLatin1String(" (");

	std::vector<std::string> filetypes = GetApp_Application().getImportTypes();
	std::vector<std::string>::const_iterator it;
	for (it=filetypes.begin();it != filetypes.end();++it) {
		if (*it != "FCStd") {
			// ignore the project file format
			formatList += QLatin1String(" *.");
			formatList += QLatin1String(it->c_str());
		}
	}

	formatList += QLatin1String(");;");

	std::map<std::string, std::string> FilterList = GetApp_Application().getImportFilters();
	std::map<std::string, std::string>::const_iterator jt;
	for (jt=FilterList.begin();jt != FilterList.end();++jt) {
		// ignore the project file format
		if (jt->first.find("(*.FCStd)") == std::string::npos) {
			formatList += QLatin1String(jt->first.c_str());
			formatList += QLatin1String(";;");
		}
	}
	formatList += QObject::tr(allFiles);

	QString selectedFilter;
	QStringList fileList = FileDialog::getOpenFileNames(getMainWindow(),
		QObject::tr("Import file"), QString(), formatList, &selectedFilter);
	SelectModule::Dict dict = SelectModule::importHandler(fileList, selectedFilter);
	// load the files with the associated modules
	for (SelectModule::Dict::iterator it = dict.begin(); it != dict.end(); ++it) {
		getGuiApplication()->importFrom(it.key().toUtf8(),
			getGuiApplication()->activeDocument()->getDocument()->getName(),
			it.value().toAscii());
	}
}

bool StdCmdImport::isActive()
{
	return true;
}

DEF_STD_CMD_A(StdCmdExport)

StdCmdExport::StdCmdExport()
:Command("Std_Export")
{
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("&Export...");
	sToolTipText  = QT_TR_NOOP("Export an object in the active document");
	sWhatsThis    = "Std_Export";
	sStatusTip    = QT_TR_NOOP("Export an object in the active document");
	//sPixmap       = "Open";
	sAccel        ="Ctrl+E";
}

void StdCmdExport::activated(int iMsg)
{

}

bool StdCmdExport::isActive()
{
	return true;
}

DEF_STD_CMD_A(StdCmdMergeProjects)

StdCmdMergeProjects::StdCmdMergeProjects()
:Command("Std_MergeProjects")
{
	sAppModule    = "File";
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("Merge project...");
	sToolTipText  = QT_TR_NOOP("Merge project");
	sWhatsThis    = QT_TR_NOOP("Merge project");
	sStatusTip    = QT_TR_NOOP("Merge project");
}

void StdCmdMergeProjects::activated(int iMsg)
{

}

bool StdCmdMergeProjects::isActive()
{
	return true;
}


//===========================================================================
// Std_New
//===========================================================================

DEF_STD_CMD(StdCmdNew);

StdCmdNew::StdCmdNew()
:Command("Std_New")
{
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("&New");
	sToolTipText  = QT_TR_NOOP("Create a new empty document");
	sWhatsThis    = "Std_New";
	sStatusTip    = QT_TR_NOOP("Create a new empty document");
	sPixmap       = "document-new";
	sAccel        = keySequenceToAccel(QKeySequence::New);
}

void StdCmdNew::activated(int iMsg)
{
	//doCommand(Command::Doc,"App.newDocument()");
	//doCommand("App.newDocument()",(CommandFunciont)App::Document::resetDocument_S);
	doCommand((CommandStringFunction)App::Document::resetDocument_S);
}

//===========================================================================
// Std_Save
//===========================================================================
DEF_STD_CMD_A(StdCmdSave);

StdCmdSave::StdCmdSave()
:Command("Std_Save")
{
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("&Save");
	sToolTipText  = QT_TR_NOOP("Save the active document");
	sWhatsThis    = "Std_Save";
	sStatusTip    = QT_TR_NOOP("Save the active document");
	sPixmap       = "document-save";
	sAccel        = keySequenceToAccel(QKeySequence::Save);
}

void StdCmdSave::activated(int iMsg)
{
#if 0
	Gui::Document* pActiveDoc = getActiveGuiDocument();
	if ( pActiveDoc )
		pActiveDoc->save();
	else
#endif
		//doCommand(Command::Gui,"Gui.sendMsgToActiveView","Save");
		//QVariant val = 0;
		//QString g = val.toString();
		doCommand((CommandStringFunction)Gui_Application::sendMsgToActiveView,"Save");

}

bool StdCmdSave::isActive(void)
{
#if 0
	if( getActiveGuiDocument() )
		return true;
	else
#endif
		return getGuiApplication()->sendHasMsgToActiveView("Save");
}

//===========================================================================
// Std_SaveAs
//===========================================================================
DEF_STD_CMD_A(StdCmdSaveAs);

StdCmdSaveAs::StdCmdSaveAs()
:Command("Std_SaveAs")
{
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("Save &As...");
	sToolTipText  = QT_TR_NOOP("Save the active document under a new file name");
	sWhatsThis    = "Std_SaveAs";
	sStatusTip    = QT_TR_NOOP("Save the active document under a new file name");
#if QT_VERSION >= 0x040200
	sPixmap       = "document-save-as";
#endif
	sAccel        = keySequenceToAccel(QKeySequence::SaveAs);
}

void StdCmdSaveAs::activated(int iMsg)
{
#if 0
	Gui::Document* pActiveDoc = getActiveGuiDocument();
	if ( pActiveDoc )
		pActiveDoc->saveAs();
	else
#endif
		//doCommand(Command::Gui,"Gui.SendMsgToActiveView(\"SaveAs\")");
}

bool StdCmdSaveAs::isActive(void)
{
#if 0
	if( getActiveGuiDocument() )
		return true;
	else
#endif
		return getGuiApplication()->sendHasMsgToActiveView("SaveAs");
}

//===========================================================================
// Std_ProjectInfo
//===========================================================================

DEF_STD_CMD_A(StdCmdProjectInfo);

StdCmdProjectInfo::StdCmdProjectInfo()
:Command("Std_ProjectInfo")
{
	// seting the 
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("Project i&nformation...");
	sToolTipText  = QT_TR_NOOP("Show details of the currently active project");
	sWhatsThis    = "Std_ProjectInfo";
	sStatusTip    = QT_TR_NOOP("Show details of the currently active project");
#if QT_VERSION >= 0x040200
	sPixmap       = "document-properties";
#endif
}

void StdCmdProjectInfo::activated(int iMsg)
{
	//Gui::Dialog::DlgProjectInformationImp dlg(getActiveGuiDocument()->getDocument(), getMainWindow());
//	dlg.exec();
}

bool StdCmdProjectInfo::isActive(void)
{
	return true;
	//return ( getActiveGuiDocument() ? true : false );
}


//===========================================================================
// Std_Quit
//===========================================================================

DEF_STD_CMD(StdCmdQuit );

StdCmdQuit::StdCmdQuit()
:Command("Std_Quit")
{
	sGroup        = QT_TR_NOOP("File");
	sMenuText     = QT_TR_NOOP("E&xit");
	sToolTipText  = QT_TR_NOOP("Quits the application");
	sWhatsThis    = "Std_Quit";
	sStatusTip    = QT_TR_NOOP("Quits the application");
#if QT_VERSION >= 0x040200
	sPixmap       = "system-log-out";
#endif
	  sAccel        = "Alt+F4";
}

void StdCmdQuit::activated(int iMsg)
{
	// close the main window and exit the event loop
	getMainWindow()->close();
}

//===========================================================================
// Std_Undo
//===========================================================================

DEF_STD_CMD_AC(StdCmdUndo);

StdCmdUndo::StdCmdUndo()
:Command("Std_Undo")
{
	sGroup        = QT_TR_NOOP("Edit");
	sMenuText     = QT_TR_NOOP("&Undo");
	sToolTipText  = QT_TR_NOOP("Undo exactly one action");
	sWhatsThis    = "Std_Undo";
	sStatusTip    = QT_TR_NOOP("Undo exactly one action");
	sPixmap       = "edit-undo";
	sAccel        = keySequenceToAccel(QKeySequence::Undo);
	eType         = ForEdit;
}

void StdCmdUndo::activated(int iMsg)
{
	//  Application::Instance->slotUndo();
	getGuiApplication()->sendMsgToActiveView("Undo");
}

bool StdCmdUndo::isActive(void)
{
	return getGuiApplication()->sendHasMsgToActiveView("Undo");
}

Action * StdCmdUndo::createAction(void)
{
	Action *pcAction;

	pcAction = new UndoAction(this,getMainWindow());
	applyCommandData(pcAction);
	if (sPixmap)
		pcAction->setIcon(BitmapFactory().pixmap(sPixmap));
	pcAction->setShortcut(QString::fromAscii(sAccel));

	return pcAction;
}

//===========================================================================
// Std_Redo
//===========================================================================

DEF_STD_CMD_AC(StdCmdRedo );

StdCmdRedo::StdCmdRedo()
:Command("Std_Redo")
{
	sGroup        = QT_TR_NOOP("Edit");
	sMenuText     = QT_TR_NOOP("&Redo");
	sToolTipText  = QT_TR_NOOP("Redoes a previously undone action");
	sWhatsThis    = "Std_Redo";
	sStatusTip    = QT_TR_NOOP("Redoes a previously undone action");
	sPixmap       = "edit-redo";
	sAccel        = keySequenceToAccel(QKeySequence::Redo);
	eType         = ForEdit;
}

void StdCmdRedo::activated(int iMsg)
{
	//  Application::Instance->slotRedo();
	getGuiApplication()->sendMsgToActiveView("Redo");
}

bool StdCmdRedo::isActive(void)
{
	return getGuiApplication()->sendHasMsgToActiveView("Redo");
}

Action * StdCmdRedo::createAction(void)
{
	Action *pcAction;

	pcAction = new RedoAction(this,getMainWindow());
	applyCommandData(pcAction);
	if (sPixmap)
		pcAction->setIcon(BitmapFactory().pixmap(sPixmap));
	pcAction->setShortcut(QString::fromAscii(sAccel));

	return pcAction;
}


//===========================================================================
// Std_Cut
//===========================================================================
DEF_STD_CMD_A(StdCmdCut);

StdCmdCut::StdCmdCut()
: Command("Std_Cut")
{
	sGroup        = QT_TR_NOOP("Edit");
	sMenuText     = QT_TR_NOOP("&Cut");
	sToolTipText  = QT_TR_NOOP("Cut out");
	sWhatsThis    = "Std_Cut";
	sStatusTip    = QT_TR_NOOP("Cut out");
	sPixmap       = "edit-cut";
    sAccel        = keySequenceToAccel(QKeySequence::Cut);
}

void StdCmdCut::activated(int iMsg)
{
	getGuiApplication()->sendMsgToActiveView("Cut");
}

bool StdCmdCut::isActive(void)
{
	return getGuiApplication()->sendHasMsgToActiveView("Cut");
}

//===========================================================================
// Std_Copy
//===========================================================================
DEF_STD_CMD_A(StdCmdCopy);

StdCmdCopy::StdCmdCopy()
: Command("Std_Copy")
{
	sGroup        = QT_TR_NOOP("Edit");
	sMenuText     = QT_TR_NOOP("C&opy");
	sToolTipText  = QT_TR_NOOP("Copy operation");
	sWhatsThis    = "Std_Copy";
	sStatusTip    = QT_TR_NOOP("Copy operation");
	sPixmap       = "edit-copy";
	sAccel        = keySequenceToAccel(QKeySequence::Copy);
}

void StdCmdCopy::activated(int iMsg)
{
// 	bool done = getGuiApplication()->sendMsgToActiveView("Copy");
// 	if (!done) {
// 		WaitCursor wc;
// 		QMimeData * mimeData = getMainWindow()->createMimeDataFromSelection();
// 		QClipboard* cb = QApplication::clipboard();
// 		cb->setMimeData(mimeData);
// 	}
}

bool StdCmdCopy::isActive(void)
{
// 	if (getGuiApplication()->sendHasMsgToActiveView("Copy"))
// 		return true;
// 	return Selection().hasSelection();

	return true;
}

//===========================================================================
// Std_Paste
//===========================================================================
DEF_STD_CMD_A(StdCmdPaste);

StdCmdPaste::StdCmdPaste()
: Command("Std_Paste")
{
	sGroup        = QT_TR_NOOP("Edit");
	sMenuText     = QT_TR_NOOP("&Paste");
	sToolTipText  = QT_TR_NOOP("Paste operation");
	sWhatsThis    = "Std_Paste";
	sStatusTip    = QT_TR_NOOP("Paste operation");
	sPixmap       = "edit-paste";
	sAccel        = keySequenceToAccel(QKeySequence::Paste);
}

void StdCmdPaste::activated(int iMsg)
{
// 	bool done = getGuiApplication()->sendMsgToActiveView("Paste");
// 	if (!done) {
// 		QClipboard* cb = QApplication::clipboard();
// 		const QMimeData* mimeData = cb->mimeData();
// 		if (mimeData) {
// 			WaitCursor wc;
// 			getMainWindow()->insertFromMimeData(mimeData);
// 		}
// 	}
}

bool StdCmdPaste::isActive(void)
{
// 	if (getGuiApplication()->sendHasMsgToActiveView("Paste"))
// 		return true;
// 	QClipboard* cb = QApplication::clipboard();
// 	const QMimeData* mime = cb->mimeData();
// 	if (!mime) return false;
// 	return getMainWindow()->canInsertFromMimeData(mime);
	return true;
}



//===========================================================================
// Std_SelectAll
//===========================================================================

DEF_STD_CMD_A(StdCmdSelectAll);

StdCmdSelectAll::StdCmdSelectAll()
: Command("Std_SelectAll")
{
	sGroup        = QT_TR_NOOP("Edit");
	sMenuText     = QT_TR_NOOP("Select &All");
	sToolTipText  = QT_TR_NOOP("Select all");
	sWhatsThis    = "Std_SelectAll";
	sStatusTip    = QT_TR_NOOP("Select all");
#if QT_VERSION >= 0x040200
	sPixmap       = "edit-select-all";
#endif
	//iAccel        = Qt::CTRL+Qt::Key_A; // superseeds shortcuts for text edits
}

void StdCmdSelectAll::activated(int iMsg)
{
// 	SelectionSingleton& rSel = Selection();
// 	App::Document* doc = App::GetApplication().getActiveDocument();
// 	std::vector<App::DocumentObject*> objs = doc->getObjectsOfType(App::DocumentObject::getClassTypeId());
// 	rSel.setSelection(doc->getName(), objs);
}

bool StdCmdSelectAll::isActive(void)
{
	return true;
	//return App::GetApplication().getActiveDocument() != 0;
}

//===========================================================================
// Std_Delete
//===========================================================================
DEF_STD_CMD_A(StdCmdDelete);

StdCmdDelete::StdCmdDelete()
:Command("Std_Delete")
{
	sGroup        = QT_TR_NOOP("Edit");
	sMenuText     = QT_TR_NOOP("&Delete");
	sToolTipText  = QT_TR_NOOP("Deletes the selected objects");
	sWhatsThis    = "Std_Delete";
	sStatusTip    = QT_TR_NOOP("Deletes the selected objects");
#if QT_VERSION >= 0x040200
	sPixmap       = "edit-delete";
#endif
	sAccel        = keySequenceToAccel(QKeySequence::Delete);
}

void StdCmdDelete::activated(int iMsg)
{
	// go through all documents
  	const SelectionSingleton& rSel = Selection();
  	const std::vector<App::Document*> docs = GetApp_Application().getDocuments();
  	for ( std::vector<App::Document*>::const_iterator it = docs.begin(); it != docs.end(); ++it ) {
  		const std::vector<App::DocumentObject*> sel = rSel.getObjectsOfType(App::DocumentObject::getClassTypeId(), (*it)->getName());
  		if (!sel.empty()) {
  			(*it)->openTransaction("Delete");
  			for(std::vector<App::DocumentObject*>::const_iterator ft=sel.begin();ft!=sel.end();ft++) {
//   				if ((*ft)->getTypeId().isDerivedFrom(App::DocumentObjectGroup::getClassTypeId()))
//  					doCommand(Doc,"App.getDocument(\"%s\").getObject(\"%s\").removeObjectsFromDocument()"
//  					,(*it)->getName(), (*ft)->getNameInDocument());

				doCommand((CommandStringFunction)App::Document::remvoeObject,(*it)->getName(), (*ft)->getNameInDocument());
//  				doCommand(Doc,"App.getDocument(\"%s\").removeObject(\"%s\")"
//  					,(*it)->getName(), (*ft)->getNameInDocument());
  			}
  			(*it)->commitTransaction();
  		}
  	}

	//doCommand(Doc,"App.Document.removeObject()"	,"");
	
}

bool StdCmdDelete::isActive(void)
{
	return true;
	//return Selection().getCompleteSelection().size() > 0;
}

void CreateDocCommands(void)
{
	CommandManager &rcCmdMgr = Gui_Application::instance->commandManager();
	rcCmdMgr.addCommand(new StdCmdNew());
	rcCmdMgr.addCommand(new StdCmdOpen());
	rcCmdMgr.addCommand(new StdCmdImport());
	rcCmdMgr.addCommand(new StdCmdDWGImport());
	rcCmdMgr.addCommand(new StdCmdTopoImport());
	rcCmdMgr.addCommand(new StdCmdExport());

	rcCmdMgr.addCommand(new StdCmdSave());
	rcCmdMgr.addCommand(new StdCmdSaveAs());
	rcCmdMgr.addCommand(new StdCmdProjectInfo());
	rcCmdMgr.addCommand(new StdCmdUndo());
	rcCmdMgr.addCommand(new StdCmdRedo());

	rcCmdMgr.addCommand(new StdCmdQuit());
	rcCmdMgr.addCommand(new StdCmdCut());
	rcCmdMgr.addCommand(new StdCmdCopy());
	rcCmdMgr.addCommand(new StdCmdPaste());
	rcCmdMgr.addCommand(new StdCmdSelectAll());
	rcCmdMgr.addCommand(new StdCmdDelete());
}






